1   /*
2    * Copyright (C) 2007 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.collect;
18  
19  import static com.google.common.truth.Truth.assertThat;
20  
21  import com.google.common.annotations.GwtCompatible;
22  
23  import junit.framework.TestCase;
24  
25  import java.util.Arrays;
26  import java.util.Collection;
27  import java.util.Comparator;
28  import java.util.Iterator;
29  import java.util.Map;
30  import java.util.Set;
31  import java.util.SortedMap;
32  
33  /**
34   * Unit tests for {@code TreeMultimap} with natural ordering.
35   *
36   * @author Jared Levy
37   */
38  @GwtCompatible(emulated = true)
39  public class TreeMultimapNaturalTest extends TestCase {
40  
41    protected SetMultimap<String, Integer> create() {
42      return TreeMultimap.create();
43    }
44  
45    /**
46     * Create and populate a {@code TreeMultimap} with the natural ordering of
47     * keys and values.
48     */
49    private TreeMultimap<String, Integer> createPopulate() {
50      TreeMultimap<String, Integer> multimap = TreeMultimap.create();
51      multimap.put("google", 2);
52      multimap.put("google", 6);
53      multimap.put("foo", 3);
54      multimap.put("foo", 1);
55      multimap.put("foo", 7);
56      multimap.put("tree", 4);
57      multimap.put("tree", 0);
58      return multimap;
59    }
60  
61    public void testToString() {
62      SetMultimap<String, Integer> multimap = create();
63      multimap.putAll("bar", Arrays.asList(3, 1, 2));
64      multimap.putAll("foo", Arrays.asList(2, 3, 1, -1, 4));
65      assertEquals("{bar=[1, 2, 3], foo=[-1, 1, 2, 3, 4]}",
66          multimap.toString());
67    }
68  
69    public void testOrderedGet() {
70      TreeMultimap<String, Integer> multimap = createPopulate();
71      assertThat(multimap.get("foo")).has().exactly(1, 3, 7).inOrder();
72      assertThat(multimap.get("google")).has().exactly(2, 6).inOrder();
73      assertThat(multimap.get("tree")).has().exactly(0, 4).inOrder();
74    }
75  
76    public void testOrderedKeySet() {
77      TreeMultimap<String, Integer> multimap = createPopulate();
78      assertThat(multimap.keySet()).has().exactly("foo", "google", "tree").inOrder();
79    }
80  
81    public void testOrderedAsMapEntries() {
82      TreeMultimap<String, Integer> multimap = createPopulate();
83      Iterator<Map.Entry<String, Collection<Integer>>> iterator =
84          multimap.asMap().entrySet().iterator();
85      Map.Entry<String, Collection<Integer>> entry = iterator.next();
86      assertEquals("foo", entry.getKey());
87      assertThat(entry.getValue()).has().exactly(1, 3, 7);
88      entry = iterator.next();
89      assertEquals("google", entry.getKey());
90      assertThat(entry.getValue()).has().exactly(2, 6);
91      entry = iterator.next();
92      assertEquals("tree", entry.getKey());
93      assertThat(entry.getValue()).has().exactly(0, 4);
94    }
95  
96    public void testOrderedEntries() {
97      TreeMultimap<String, Integer> multimap = createPopulate();
98      assertThat(multimap.entries()).has().exactly(
99          Maps.immutableEntry("foo", 1),
100         Maps.immutableEntry("foo", 3),
101         Maps.immutableEntry("foo", 7),
102         Maps.immutableEntry("google", 2),
103         Maps.immutableEntry("google", 6),
104         Maps.immutableEntry("tree", 0),
105         Maps.immutableEntry("tree", 4)).inOrder();
106   }
107 
108   public void testOrderedValues() {
109     TreeMultimap<String, Integer> multimap = createPopulate();
110     assertThat(multimap.values()).has().exactly(
111         1, 3, 7, 2, 6, 0, 4).inOrder();
112   }
113 
114   public void testMultimapConstructor() {
115     SetMultimap<String, Integer> multimap = create();
116     multimap.putAll("bar", Arrays.asList(3, 1, 2));
117     multimap.putAll("foo", Arrays.asList(2, 3, 1, -1, 4));
118     TreeMultimap<String, Integer> copy = TreeMultimap.create(multimap);
119     assertEquals(multimap, copy);
120   }
121 
122   private static final Comparator<Double> KEY_COMPARATOR =
123       Ordering.natural();
124 
125   private static final Comparator<Double> VALUE_COMPARATOR =
126       Ordering.natural().reverse().nullsFirst();
127 
128   /**
129    * Test that creating one TreeMultimap from another does not copy the
130    * comparators from the source TreeMultimap.
131    */
132   public void testCreateFromTreeMultimap() {
133     Multimap<Double, Double> tree = TreeMultimap.create(KEY_COMPARATOR, VALUE_COMPARATOR);
134     tree.put(1.0, 2.0);
135     tree.put(2.0, 3.0);
136     tree.put(3.0, 4.0);
137     tree.put(4.0, 5.0);
138 
139     TreeMultimap<Double, Double> copyFromTree = TreeMultimap.create(tree);
140     assertEquals(tree, copyFromTree);
141     assertSame(Ordering.natural(), copyFromTree.keyComparator());
142     assertSame(Ordering.natural(), copyFromTree.valueComparator());
143     assertSame(Ordering.natural(), copyFromTree.get(1.0).comparator());
144   }
145 
146   /**
147    * Test that creating one TreeMultimap from a non-TreeMultimap
148    * results in natural ordering.
149    */
150   public void testCreateFromHashMultimap() {
151     Multimap<Double, Double> hash = HashMultimap.create();
152     hash.put(1.0, 2.0);
153     hash.put(2.0, 3.0);
154     hash.put(3.0, 4.0);
155     hash.put(4.0, 5.0);
156 
157     TreeMultimap<Double, Double> copyFromHash = TreeMultimap.create(hash);
158     assertEquals(hash, copyFromHash);
159     assertEquals(Ordering.natural(), copyFromHash.keyComparator());
160     assertEquals(Ordering.natural(), copyFromHash.valueComparator());
161   }
162 
163   /**
164    * Test that creating one TreeMultimap from a SortedSetMultimap uses natural
165    * ordering.
166    */
167   public void testCreateFromSortedSetMultimap() {
168     SortedSetMultimap<Double, Double> tree = TreeMultimap.create(KEY_COMPARATOR, VALUE_COMPARATOR);
169     tree.put(1.0, 2.0);
170     tree.put(2.0, 3.0);
171     tree.put(3.0, 4.0);
172     tree.put(4.0, 5.0);
173 
174     SortedSetMultimap<Double, Double> sorted = Multimaps.unmodifiableSortedSetMultimap(tree);
175     TreeMultimap<Double, Double> copyFromSorted = TreeMultimap.create(sorted);
176     assertEquals(tree, copyFromSorted);
177     assertSame(Ordering.natural(), copyFromSorted.keyComparator());
178     assertSame(Ordering.natural(), copyFromSorted.valueComparator());
179     assertSame(Ordering.natural(), copyFromSorted.get(1.0).comparator());
180   }
181 
182   public void testComparators() {
183     TreeMultimap<String, Integer> multimap = TreeMultimap.create();
184     assertEquals(Ordering.natural(), multimap.keyComparator());
185     assertEquals(Ordering.natural(), multimap.valueComparator());
186   }
187 
188   public void testTreeMultimapAsMapSorted() {
189     TreeMultimap<String, Integer> multimap = createPopulate();
190     SortedMap<String, Collection<Integer>> asMap = multimap.asMap();
191     assertEquals(Ordering.natural(), asMap.comparator());
192     assertEquals("foo", asMap.firstKey());
193     assertEquals("tree", asMap.lastKey());
194     Set<Integer> fooValues = ImmutableSet.of(1, 3, 7);
195     Set<Integer> googleValues = ImmutableSet.of(2, 6);
196     Set<Integer> treeValues = ImmutableSet.of(4, 0);
197     assertEquals(ImmutableMap.of("google", googleValues, "tree", treeValues),
198         asMap.tailMap("g"));
199     assertEquals(ImmutableMap.of("google", googleValues, "foo", fooValues),
200         asMap.headMap("h"));
201     assertEquals(ImmutableMap.of("google", googleValues),
202         asMap.subMap("g", "h"));
203   }
204 
205   public void testTailSetClear() {
206     TreeMultimap<String, Integer> multimap = TreeMultimap.create();
207     multimap.put("a", 1);
208     multimap.put("a", 11);
209     multimap.put("b", 2);
210     multimap.put("c", 3);
211     multimap.put("d", 4);
212     multimap.put("e", 5);
213     multimap.put("e", 55);
214 
215     multimap.keySet().tailSet("d").clear();
216     assertEquals(ImmutableSet.of("a", "b", "c"), multimap.keySet());
217     assertEquals(4, multimap.size());
218     assertEquals(4, multimap.values().size());
219     assertEquals(4, multimap.keys().size());
220   }
221 }
222